home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
VideoToolbox 96.06.15
/
VideoToolboxSources
/
CopyWindows.c
< prev
next >
Wrap
Text File
|
1995-07-26
|
9KB
|
218 lines
/*
CopyWindows.c
CopyWindows(srcWindow,dstWindow,srcRectPtr,dstRectPtr,srcMode,maskRgn);
CopyWindows() provides a high-level interface to CopyBits and CopyBitsQuickly,
accepting windows (WindowPtr, CWindowPtr, or GWorldPtr) instead of pixmaps or
bitmaps.
You select CopyBitsQuickly by using a srcMode that has the "copyLiterally" bit
set, i.e. either srcCopyLiterally, addOverLiterally, addOverParallelLiterally,
or mulOverLiterally.
For your convenience, CopyWindows normally sets up the foreground and background
colors to prevent undesired colorizing. If you want to colorize then add
"copyColorize" to the srcMode argument.
CopyBits() is an extremely useful component of QuickDraw, but it's tricky to
use, especially if you just want a faithful copy. Its user-interface was frozen
a long time ago, when off-screen images were referred to by their BitMap
pointers. Apple generalized its underlying code to accept PixMap pointers as
well, but the reality is that nowadays the object that we work with is a window,
either on-screen, or off-screen (i.e. a GWorld). CopyWindows accepts two
windows, source and destination, figures out where the associated Pix/BitMaps
are, and calls CopyBits or CopyBitsQuickly, after making all the appropriate
incantations to get the desired results.
The allowed values for srcMode are documented by Apple along with CopyBits in the
New Inside Mac: "Imaging with QuickDraw". The additional modes implemented by
CopyBitsQuickly are documented in CopyBitsQuickly.c. CopyBits and
CopyBitsQuickly define srcMode as a short. CopyWindows defines srcMode as a
long, using two bits in the upper word as flags for copyLiterally and
copyColorize. Here's a summary of the modes that I use most:
srcCopy
This mode is implemented by CopyBits. If the source and destination have the
same depth (i.e. pixelSize) and exactly the same color table then you'll get
faithful copying of the actual numbers stored in each pixel. (I'm assuming that
the destination window has the same color table as its device, which will be
true if you created the window using GDOpenWindow or NewGWorld.) If the source
and destination have different color tables, e.g. because the pixel sizes
differ, then CopyBits will translate via the color tables. CopyBits is perhaps
Apple's prize piece of code and runs very fast, taking advantage of special
instructions of particular processors (e.g. to do 64 bit moves on 68040 and
PowerPC) and can do wonderful things, like stretch and shrink and mask by a
region. Apple defines many other srcMode values but I never use them with
CopyBits because they all result in color translations that I don't want.
srcCopyLiterally,addOverLiterally,addOverParallelLiterally,mulOverLiterally
These modes are implemented by CopyBitsQuickly, which never does color
translation. addOverLiterally adds the pixel values, ignoring overflow.
addOverParallelLiterally does the same, but does the addition for 32-bits at a
time, adding several pixels at once, so that if overflow occurs it will overflow
into an adjoing pixel. mulOverLiterally multiplies the (unsigned) pixels,
divides the product by 128, and stores the result in the destination.
CopyBitsQuickly has many restrictions. The source and destination must have the
same rect size and the same pixel size. addOverLiterally and mulOverLiterally
insist on 8-bit pixels. All the modes resolve only bytes, not bits, so a few
bits at the left and right of your image may not be copied if that would require
writing to a byte not all of whose bits are in the destination.
NOTES:
0. Read "VideoToolbox:Notes:CopyBits slavishly".
1. CopyBits has a rarely used feature called "colorizing" whereby if the
foreground and background colors of the current port are not black and white
then each source pixel's color is translated by linear interpolation between the
foreground and background color. Programmers often forget about this, and are
surprised by the undesired colorizing. To make life easier I've defined an extra
bit in srcMode. If the "copyColorize" flag is false (nearly always the case)
then CopyWindows will make sure no colorizing occurs by setting the fore and
back colors to black and white. (The colors are restored before returning.)
2. Apple's CopyBits uses the color table and palette of the source pixmap as
you'd expect, but ignores the color table and palette of the destination pixmap,
and instead uses the color table of the current device. This is annoying, and
hard to remember. Apple did it this way because CopyBits uses the inverse color
table, which takes a long time to compute, and they decided that it would be too
time and memory intensive to maintain an inverse table for each window, so
instead they maintain them only for devices. The operating system creates
inverse color tables for all graphic devices. Thus it is important to remember
to set the device before calling CopyBits. To save you the trouble, CopyWindows
sets the device to be whatever device is associated with the destination window.
The device is found by GetWindowDevice(), which, for an on-screen window,
returns the screen device with largest intersection with the window's content,
and for an off-screen window (i.e. GWorld), returns the GWorld's device. When
you create your GWorld you should supply the color table of your device,
(*(*device)->gdPMap)->pmTable, if you'll later be copying from the GWorld
to the device.
3. CopyWindowsQuickly calls ShieldCursor(), to make up for the fact that
CopyBitsQuickly doesn't. QuickDraw automatically calls ShieldCursor for all
screen-drawing operations, but CopyBitsQuickly bypasses QuickDraw. The obvious
cosmetic benefit of calling ShieldCursor is that it prevents the cursor from
appearing within screen areas that are being read or written. A further, subtle,
benefit of calling ShieldCursor is compatibility with the one or two video
devices, e.g. Radius PowerView, that depend on notification from QuickDraw that
they've been written to. According to the programmer who wrote the PowerView
driver, it's enough to call ShieldCursor(), specifying the global rect that was
modified. That's hard to do within CopyBitsQuickly because the PixMap doesn't
have any global coordinates; it merely has local coordinates and the address of
video memory. (One would have to use the video address to figure out the device,
and get the global coordinates from the device.) But it's easy to call
ShieldCursor from within CopyWindowsQuickly, since it has access to the windows,
which include the necessary global coordinates.
HISTORY:
10/3/94 dgp wrote it.
11/5/94 dgp added the new flags copyLiterally and copyColorize.
*/
#include "VideoToolbox.h"
static int CopyWindowsQuickly(CWindowPtr srcWindow,CWindowPtr dstWindow
,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn);
int CopyWindows(CWindowPtr srcWindow,CWindowPtr dstWindow
,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn)
{
GWorldPtr oldPort;
GDHandle oldDevice,device;
int error;
static const RGBColor blackRGB={0,0,0},whiteRGB={0xFFFF,0xFFFF,0xFFFF};
RGBColor foreRGB,backRGB;
ColorSpec foreColor,backColor;
BitMap *srcBits,*dstBits;
static Boolean qd8,qd32,firstTime=1;
Boolean colorize;
if(srcMode & copyLiterally)
return CopyWindowsQuickly(srcWindow,dstWindow,srcRectPtr,dstRectPtr,srcMode,maskRgn);
colorize=(srcMode©Colorize)!=0;
srcMode&=0xffff; // no more need for upper bits.
if(firstTime){
long qd;
Gestalt(gestaltQuickdrawVersion,&qd);
qd8 = qd>=gestalt8BitQD;
qd32 = qd>=gestalt32BitQD;
firstTime=0;
}
device=GetWindowDevice((WindowPtr)dstWindow);
if(qd32){
GetGWorld(&oldPort,&oldDevice);
SetGWorld((GWorldPtr)dstWindow,device);
}else{
GetPort((WindowPtr *)&oldPort);
SetPort((WindowPtr)dstWindow);
if(qd8){
oldDevice=GetGDevice();
SetGDevice(device);
}
}
if(!colorize && qd8){
GetForeColor(&foreRGB);
GetBackColor(&backRGB);
if(qd32){
SaveFore(&foreColor);
SaveBack(&backColor);
}
RGBForeColor(&blackRGB); /* so CopyBits won't colorize */
RGBBackColor(&whiteRGB); /* so CopyBits won't colorize */
}
srcBits=GetBitMapPtr(srcWindow);
dstBits=GetBitMapPtr(dstWindow);
if(srcBits==NULL || dstBits==NULL)return -1;
CopyBits(srcBits,dstBits,srcRectPtr,dstRectPtr,srcMode,maskRgn);
error=QDError();
if(!colorize && qd8){
RGBForeColor(&foreRGB);
RGBBackColor(&backRGB);
if(qd32){
RestoreFore(&foreColor);
RestoreBack(&backColor);
}
}
if(qd32){
SetGWorld(oldPort,oldDevice);
}else{
SetPort((WindowPtr)oldPort);
if(qd8)SetGDevice(oldDevice);
}
return error;
}
static int CopyWindowsQuickly(CWindowPtr srcWindow,CWindowPtr dstWindow
,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn)
{
int error,i,shields=0;
BitMap *srcBits,*dstBits;
Point pt;
WindowPtr oldPort;
GetPort(&oldPort);
if(!IsGWorldPtr(srcWindow)){
SetPort((WindowPtr)srcWindow);
pt.h=pt.v=0;
LocalToGlobal(&pt);
ShieldCursor(srcRectPtr,pt);
shields++;
}
if(!IsGWorldPtr(dstWindow)){
SetPort((WindowPtr)dstWindow);
pt.h=pt.v=0;
LocalToGlobal(&pt);
ShieldCursor(dstRectPtr,pt);
shields++;
}
SetPort(oldPort);
srcBits=GetBitMapPtr(srcWindow);
dstBits=GetBitMapPtr(dstWindow);
if(srcBits==NULL || dstBits==NULL)return 4;
error=CopyBitsQuickly(srcBits,dstBits,srcRectPtr,dstRectPtr,srcMode,maskRgn);
for(i=0;i<shields;i++)ShowCursor();
return error;
}